#!/usr/bin/python3
import subprocess
import sys

from py_ini_config_modules.common_functions import *
from py_ini_config_modules.nosection_functions import *
from py_ini_config_modules.system_functions import write_config_to_file, get_comment_symbol

version = '2.1'

argv = sys.argv

commands = (
    'comment',
    'del',
    'get',
    'is_set',
    'set',
    'add',
    'uncomment',
    'del_section',
    'get_commented',
    'is_empty',
    'rename',
    '-V',
    '--version'
)

correct_flags = (
    '-n',
    '--no-section',
    '-c',
    '--create',
    '-s',
    '--no-indent',
    '-S',
    '-f',
    '--flush'
)

correct_flags_to_be_removed = (
    '-a',
    '--all',
    '-e',
    '--semicolon-comment',
    '--view-comments',
    '-i',
    '--sort-collected',
    '-v',
    '--verbose',
    '--shadowing'
)

if '-V' in argv or '--version' in argv:
    print(f'py-ini-config version {version}')
    sys.exit(0)

separator = '='
if '-s' in argv:
    key_index = argv.index('-s')
    if key_index != len(argv) - 1:
        separator = argv[key_index + 1]
        argv = argv[:key_index] + argv[key_index + 2:]
    else:
        argv = argv[:key_index] + argv[key_index + 1:]

values_separator = ','
if '-S' in argv:
    sindex = argv.index('-S')
    if sindex == len(argv) - 1:
        print('Необходимо указать разделитель для значений параметра')
        sys.exit()
    values_separator = argv[sindex + 1]
    argv = argv[:sindex] + argv[sindex + 2:]

files_to_recursive_scan = []
if '--all' in argv or '-a' in argv:
    if 'get' not in argv and 'is_set' not in argv:
        print('Флаг -a, --all можно использовать только с командами get или is_set')
        sys.exit(0)
    for i in range(len(argv)):
        if argv[i] == '--all':
            argv[i] = '-a'
while '-a' in argv:
    aindex = argv.index('-a')
    if aindex != len(argv) - 1:
        files_to_recursive_scan.append(argv[aindex + 1])
        argv = argv[:aindex] + argv[aindex + 2:]
    else:
        argv.remove('-a')

required_extension = None
if '-e' in argv:
    eindex = argv.index('-e')
    if eindex == len(argv) - 1:
        print('Необходимо указать требуемое расширение')
        sys.exit(0)
    required_extension = argv[eindex + 1]
    argv = argv[:eindex] + argv[eindex + 2:]

noindent = False
if '--no-indent' in argv:
    noindent = True
    argv.remove('--no-indent')

com_symbol = '#'
if '--semicolon-comment' in argv:
    com_symbol = ';'
    argv.remove('--semicolon-comment')

view_comments = False
if '--view-comments' in argv:
    view_comments = True
    argv.remove('--view-comments')

flush = False
if '-f' in argv:
    argv.remove('-f')
    flush = True
elif '--flush' in argv:
    argv.remove('--flush')
    flush = True

inversed_order = False
if '-i' in argv:
    argv.remove('-i')
    inversed_order = True

sort_collected = False
if '--sort-collected' in argv:
    argv.remove('--sort-collected')
    sort_collected = True

verbose = False
if '-v' in argv or '--verbose' in argv:
    if '-v' in argv:
        argv.remove('-v')
    else:
        argv.remove('--verbose')
    verbose = True

shadowing = False
if '--shadowing' in argv:
    argv.remove('--shadowing')
    shadowing = True

non_existing_flags = [i for i in argv if i.startswith('-') and i not in correct_flags]
while non_existing_flags:
    flag = non_existing_flags.pop()
    if verbose:
        eprint(f'Флаг {flag} не поддерживается данной программой')
    argv.remove(flag)
# Creating config file

if ('--create' in argv or '-c' in argv) and len(argv) >= 4 and os.path.isfile(argv[3]):
    print(f'Внимание: файл {argv[3]} существует. Флаг --create будет проигнорирован.')
    if '--create' in argv:
        argv.remove('--create')
    else:
        argv.remove('-c')

if '--create' in argv or '-c' in argv:
    if 'set' not in argv and 'add' not in argv:
        eprint('Ошибка - создание файла возможно только с опцией set или add.')
        sys.exit(1)
    if '--create' in argv:
        indx = argv.index('--create')
    else:
        indx = argv.index('-c')
    if indx == len(argv) - 1:
        eprint('Ошибка - вы не указали имя файла для создания.')
        sys.exit(1)
    filename = argv[indx + 1]
    subprocess.run(f'touch {filename}', shell=True)
    argv = argv[:indx] + argv[indx + 2:]
    if len(argv) < 5:
        print('Для установления или добавления значения переменной в новом файле должно не менее 4 параметров '
              'командной строки.')
        print('Синтаксис: py-ini-config set | add [-c, --create] filename [section, -n, --no-section]'
              ' var value [-s separator] [--no-indent]')
        sys.exit()
    if '-n' in argv or '--no-section' in argv:
        if '-n' in argv:
            argv.remove('-n')
        else:
            argv.remove('--no-section')
        config = ini_config_set_nosection(filename, argv[2], argv[3], noindent, com_symbol, view_comments,
                                          separator=separator)
    else:
        config = ini_config_set(filename, argv[2], argv[3], argv[4], noindent, com_symbol, view_comments,
                                separator=separator)
    write_config_to_file(config, filename)

# Working with config files with no sections

elif '-n' in argv or '--no-section' in argv:
    if '-n' in argv:
        argv.remove('-n')
    else:
        argv.remove('--no-section')

    if len(argv) < 3:
        eprint('Ошибка - недостаточно команд.')
        sys.exit(1)
    elif argv[1] not in commands:
        eprint('Ошибка - неизвестная команда.')
        sys.exit(1)
    elif not os.path.isfile(argv[2]) and not files_to_recursive_scan:
        eprint('Ошибка - указанный файл не существует.')
        sys.exit(1)
    else:
        # trim_empty_strings(argv[2])
        if com_symbol == '#' and not files_to_recursive_scan:
            com_symbol = get_comment_symbol(argv[2])
        if argv[1] == 'set':
            if len(argv) != 5:
                print(
                    'Для установления значения переменной вне секции должно быть не менее 5 параметров командной '
                    'строки.')
                print('Синтаксис: py-ini-config set file [-n, --no-section] var value [-s separator]')
                sys.exit()
            config = ini_config_set_nosection(argv[2], argv[3], argv[4], noindent, com_symbol, view_comments,
                                              separator=separator)
            write_config_to_file(config, argv[2])

        elif argv[1] == 'comment':
            if len(argv) != 4:
                print('Для комментирования переменной вне секции должно быть не менее 4 параметров командной строки.')
                print('Синтаксис: py-ini-config comment file [-n, --no-section] var [-s separator]')
                sys.exit()
            else:
                config = ini_config_comment_nosection(argv[2], argv[3], com_symbol, separator=separator)
            if config is not False:
                write_config_to_file(config, argv[2])
            else:
                sys.exit(1)

        elif argv[1] == 'del':
            if len(argv) < 4:
                print('Для удаления переменной или её значения вне секции должно быть не менее 4 параметров командной '
                      'строки.')
                print('Синтаксис: py-ini-config del file [-n, --no-section] var [value] [-s separator] [-S '
                      'values_separator]')
                sys.exit()
            if len(argv) > 4:
                value = argv[4]
            else:
                value = None
            config = ini_config_del_nosection(argv[2], argv[3], com_symbol, separator=separator,
                                              values_separator=values_separator, value=value)
            if config is not False:
                write_config_to_file(config, argv[2])
            else:
                sys.exit(1)

        elif argv[1] == 'get':
            if len(argv) != 4 and not files_to_recursive_scan:
                print(
                    'Для получения значения переменной вне секции должно быть не менее 4 параметров командной строки.')
                print('Синтаксис: py-ini-config get file [-n, --no-section] var [-s separator]')
                sys.exit()
            if files_to_recursive_scan:
                res = ini_config_get_recursive_nosection(argv[2], separator=separator,
                                                         inversed_order=inversed_order,
                                                         files_to_recursive_scan=files_to_recursive_scan,
                                                         required_extension=required_extension,
                                                         sort_collected=sort_collected,
                                                         shadowing=shadowing,
                                                         verbose=verbose)
            else:
                res = ini_config_get_nosection(argv[2], argv[3], separator=separator)
            if res:
                print(res)
            else:
                sys.exit(1)

        elif argv[1] == 'is_set':
            if len(argv) < 4 and not files_to_recursive_scan:
                print('Для определения существования значения переменной вне секции должно быть не меньше 4 параметров '
                      'командной строки.')
                print('Синтаксис: py-ini-config is_set file [-n , --no-section] var [value] [-s separator]')
                sys.exit()
            if files_to_recursive_scan:
                sys.exit(ini_config_is_set_nosection_recursive(argv[2], value=argv[3] if len(argv) >= 4 else None,
                                                               separator=separator,
                                                               values_separator=values_separator,
                                                               files_to_recursive_scan=files_to_recursive_scan,
                                                               shadowing=shadowing,
                                                               required_extension=required_extension,
                                                               sort_collected=sort_collected,
                                                               verbose=verbose
                                                               ))
            if len(argv) == 4:
                value = None
            else:
                value = argv[4]
            sys.exit(ini_config_is_set_nosection(argv[2], argv[3], value=value, separator=separator,
                                                 values_separator=values_separator))

        elif argv[1] == 'uncomment':
            if len(argv) != 4:
                print('Для снятия комментария с переменной вне секции должно быть не менее 4 параметров '
                      'командной строки.')
                print('Синтаксис: py-ini-config uncomment file [-n , --no-section] var [-s separator]')
                sys.exit()
            else:
                config = ini_config_uncomment_nosection(argv[2], argv[3], com_symbol, separator=separator)
            if config is not False:
                write_config_to_file(config, argv[2])
            else:
                sys.exit(1)

        elif argv[1] == 'get_commented':
            if len(argv) != 4:
                print('Для получения значения закомментированной переменной вне секции должно быть не менее 4 '
                      'параметров командной строки.')
                print('Синтаксис: py-ini-config get_commented file [-n, --no-section] var [-s separator]')
                sys.exit()
            res = ini_config_get_commented_nosection(argv[2], argv[3], com_symbol, separator=separator)
            if res:
                print(*res, sep='\n')
            else:
                sys.exit(1)

        elif argv[1] == 'add':
            if len(argv) != 5:
                print('Для добавления значения переменной вне секции должно быть не менее 5 '
                      'параметров командной строки.')
                print('Синтаксис: py-ini-config add file [-n, --no-section] var value [-s separator] [-S '
                      'values_separator]')
                sys.exit()
            config = ini_config_add_nosection(argv[2], argv[3], argv[4], noindent, com_symbol,
                                              view_comments, separator=separator, values_separator=values_separator)
            if config:
                write_config_to_file(config, argv[2])
            else:
                sys.exit(1)

        elif argv[1] == 'rename':
            if len(argv) != 5:
                print('Для переименования переменной вне секции должно быть не менее 5 '
                      'параметров командной строки.')
                print('Синтаксис: py-ini-config rename file [-n, --no-section] var new_name [-s separator] [-S '
                      'values_separator]')
                sys.exit()
            config = ini_config_rename_nosection(argv[2], argv[3], argv[4], separator=separator)
            if config:
                write_config_to_file(config, argv[2])
            else:
                sys.exit(1)


elif len(argv) < 4:
    eprint('Ошибка - недостаточно параметров.')
    sys.exit(1)
elif argv[1] not in commands:
    eprint('Ошибка - неизвестная команда.')
    sys.exit(1)
elif not os.path.isfile(argv[2]) and not files_to_recursive_scan:
    eprint('Ошибка - указанный файл не существует.')
    sys.exit(1)
else:
    # trim_empty_strings(argv[2])
    if com_symbol == '#' and not files_to_recursive_scan:
        com_symbol = get_comment_symbol(argv[2])
    if argv[1] == 'set':
        if len(argv) != 6:
            print('Для установления значения переменной в секции должно быть не менее 5 параметров командной строки.')
            print('Синтаксис: py-ini-config set file section var value [-s separator]')
            sys.exit()
        config = ini_config_set(argv[2], argv[3], argv[4], argv[5], noindent, com_symbol, view_comments,
                                separator=separator)
        write_config_to_file(config, argv[2])

    elif argv[1] == 'comment':
        if len(argv) < 4:
            print('Для комментирования переменной в секции должно быть не менее 3 параметров командной строки.')
            print('Синтаксис: py-ini-config comment file section [var] [-s separator]')
            sys.exit()
        # Указана переменная
        if len(argv) == 5:
            config = ini_config_comment(argv[2], argv[3], com_symbol, argv[4], separator=separator)
        else:
            config = ini_config_comment(argv[2], argv[3], com_symbol, separator=separator)
        if config is not False:
            write_config_to_file(config, argv[2])
        else:
            sys.exit(1)

    elif argv[1] == 'del':
        if len(argv) < 5:
            print('Для удаления переменной или её значения в секции должно быть не менее 4 '
                  'параметров командной строки.')
            print('Синтаксис: py-ini-config del file section var [value] [-f, --flush] [-s separator] '
                  '[-S values_separator]')
            sys.exit()

        if len(argv) > 5:
            value = argv[5]
        else:
            value = None
        config = ini_config_del(argv[2], argv[3], argv[4], flush, com_symbol, separator=separator, value=value,
                                values_separator=values_separator)
        if config is not False:
            write_config_to_file(config, argv[2])
        else:
            sys.exit(1)

    elif argv[1] == 'get':
        if len(argv) < 4 and not files_to_recursive_scan:
            print('Для получения значения переменной в секции должно быть не менее 3 параметров командной строки.')
            print('Синтаксис: py-ini-config get file section [var] [-s separator]')
            sys.exit()
        if files_to_recursive_scan:
            res = ini_config_get_recursive(argv[2], argv[3], separator=separator, inversed_order=inversed_order,
                                           files_to_recursive_scan=files_to_recursive_scan,
                                           required_extension=required_extension,
                                           sort_collected=sort_collected,
                                           shadowing=shadowing,
                                           verbose=verbose)
        else:
            if len(argv) == 4:
                var = None
            else:
                var = argv[4]
            res = ini_config_get(argv[2], argv[3], var, separator=separator)
        if res:
            print(res)
        else:
            sys.exit(1)

    elif argv[1] == 'is_set':
        if len(argv) < 4 and not files_to_recursive_scan:
            print(
                'Для определения существования переменной в секции должно быть от 4 до 6 параметров командной строки.')
            print('Синтаксис: py-ini-config is_set file section [var] [value] [-s separator]')
            sys.exit()
        if files_to_recursive_scan:
            sys.exit(ini_config_is_set_recursive(argv[2], argv[3], argv[4] if len(argv) >= 5 else None,
                                                 separator=separator,
                                                 values_separator=values_separator,
                                                 files_to_recursive_scan=files_to_recursive_scan,
                                                 shadowing=shadowing,
                                                 sort_collected=sort_collected,
                                                 verbose=verbose,
                                                 required_extension=required_extension))
        if len(argv) < 5:
            var = None
        else:
            var = argv[4]
        if len(argv) < 6:
            value = None
        else:
            value = argv[5]
        sys.exit(ini_config_is_set(argv[2], argv[3], var, value, separator=separator,
                                   values_separator=values_separator))

    elif argv[1] == 'uncomment':
        if len(argv) < 4:
            print('Для снятия комментирования переменной в секции должно быть не менее 3 параметров командной строки.')
            print('Синтаксис: py-ini-config uncomment file section [var] [-s separator]')
            sys.exit()
        if len(argv) == 4:
            var = None
        else:
            var = argv[4]

        config = ini_config_uncomment(argv[2], argv[3], com_symbol, var=var, separator=separator)

        if config is not False:
            write_config_to_file(config, argv[2])
        else:
            sys.exit(1)

    elif argv[1] == 'del_section':
        if len(argv) != 4:
            print('Для удаления секции должно быть не менее 3 параметров командной строки.')
            print('Синтаксис: py-ini-config del_section file section [-s separator]')
            sys.exit()
        config = ini_config_del_section(argv[2], argv[3], separator=separator)
        if config is not False:
            write_config_to_file(config, argv[2])
        else:
            sys.exit(1)

    elif argv[1] == 'get_commented':
        if len(argv) != 5:
            print(
                'Для получения значения закомментированной переменной в секции должно быть не менее 4 параметров '
                'командной строки.')
            print('Синтаксис: py-ini-config get_commented file section var [-s separator]')
            sys.exit()
        res = ini_config_get_commented(argv[2], argv[3], argv[4], com_symbol, separator=separator)
        if res:
            print(*res, sep='\n')
        else:
            sys.exit(1)

    elif argv[1] == 'is_empty':
        if len(argv) != 4:
            print('Для определения наличия переменных в секции должно быть не менее 3 параметров командной строки.')
            print('Синтаксис: py-ini-config is_empty file section [-s separator]')
            sys.exit()
        sys.exit(ini_config_is_empty(argv[2], argv[3], separator=separator))

    elif argv[1] == 'add':
        if len(argv) != 6:
            print('Для добавления значения переменной в секции должно быть не менее 5 параметров командной строки.')
            print('Синтаксис: py-ini-config add file section var value [-s separator] [-S values_separator]')
            sys.exit()

        config = ini_config_add(argv[2], argv[3], argv[4], argv[5], noindent, com_symbol, view_comments,
                                separator=separator, values_separator=values_separator)
        write_config_to_file(config, argv[2])

    elif argv[1] == 'rename':
        if len(argv) != 6:
            print('Для переименования переменной в секции должно быть не менее 5 параметров командной строки.')
            print('Синтаксис: py-ini-config rename file section var new_name [-s separator]')
            sys.exit()
        config = ini_config_rename(argv[2], argv[3], argv[4], argv[5], separator=separator)
        if config:
            write_config_to_file(config, argv[2])
        else:
            sys.exit(1)
